package org.wpahs.ahn.rssfeed;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.content.Context;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.support.v4.widget.DrawerLayout;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wpahs.ahn.rssfeed.DB.DBFeedItem;
import org.wpahs.ahn.rssfeed.DB.DBMyFeed;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;


public class MainActivity extends ActionBarActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks{

    /**
     * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
     */
    public NavigationDrawerFragment mNavigationDrawerFragment;
    public int currentFeedId = 0;

    /**
     * Used to store the last screen title. For use in {@link #restoreActionBar()}.
     */
    private CharSequence mTitle;
    private RSSGetService mService;
    private Boolean mServiceBound = false;
    private Boolean inSettings = false;
    private Boolean mAttemptedToRefreshWhileNotBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mNavigationDrawerFragment = (NavigationDrawerFragment)
                getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
        mTitle = getTitle();

        // Set up the drawer.
        mNavigationDrawerFragment.setUp(
                R.id.navigation_drawer,
                (DrawerLayout) findViewById(R.id.drawer_layout));


        // on startup let's do some cleanup
        DBFeedItem db = new DBFeedItem(this);
        //clear out old items.  still playing with this.  trying to find the right period
        //of time to clear old feeds that were read.
        db.clearTableOfXDayOldItems(getResources().getInteger(R.integer.DaysBackToDelete));
        //since we no don't look at previously read messages in Nahp!  We might as well
        //clear out their images from the DB to save some space
        db.clearTableOfReadImages();
        db.close();
        //String html = "<img src=\"http://cdn.co-optim.us/cache/headers/2015/2102015.evolve-tackle.jpg\"><p><strong><a href=\"http://www.co-optimus.com/related-news/evolve\">Evolve </a></strong>is out today on the PC, PlayStation 4 and Xbox One. The game has been touted as a four vs one affair, and for the most part that&#39;s true. In fact, when playing competitively it&#39;s tough to even discern there&#39;s a real man or woman pulling the puppet strings of that monster. Still if you want to keep things purely co-op and take on a nasty AI computer opponent, <em>Evolve </em>gives you options.</p><p>In fact, <em>Evolve </em>offers a ton of options in its gameplay. While the technical Alpha and Beta focused on the game&#39;s Hunt mode of play, there&#39;s are four other variants to check out, with each map also given additional modifiers to make it easier or more difficult. These features make up Evacuation Mode, a sort of mini campaign set across five maps. Win a map and you&#39;ll get a bonus for the next round, lose, and you&#39;re going to have an extra challenge. That said the game does auto balance things out so the scales don&#39;t tip too far.</p><p><img alt=\"\" src=\"http://www.co-optimus.com/images/upload/image/2015/2015-02-09_00005.jpg\" style=\"width: 600px; height: 338px;\" /></p><p>As you can see from the results, out our first attempt through an Evacuation Mode was a difficult one. You can check out the video of the mini-campaign below. It takes about 45 minutes to an hour to play each mini-campaign and the maps, monsters and mutators end up being randomized giving the game a lot of replayability.</p><p>&nbsp;</p><div><iframe allowfullscreen=\"\" frameborder=\"0\" height=\"360\" src=\"https://www.youtube.com/embed/AP_XAZLExJ0\" width=\"640\"></iframe></div><p>&nbsp;</p><p>We&#39;ll have a full review of <em>Evolve </em>early next week once the server population really starts hitting the game. We should have a co-op FAQ up shortly as well. We had a ton of fun last night and there&#39;s definitely a lot of potential here. The PC version really feels cleaned up since the beta and performance was solid all around.&nbsp;For now sit back and watch the game&#39;s launch trailer to get <em>monster</em>&nbsp;hype.&nbsp;</p><p>&nbsp;</p><div><iframe allowfullscreen=\"\" frameborder=\"0\" height=\"360\" src=\"https://www.youtube.com/embed/695Z76yw-28\" width=\"640\"></iframe></div><p>&nbsp;</p><br><a href=\"http://www.co-optimus.com/article/12811/watch-us-tackle-evolve-s-evacuation-mode-in-4-player-co-op.html\">Read More</a><div class=\"feedflare\"><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:yIl2AUoC8zA\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?d=yIl2AUoC8zA\" border=\"0\"></img></a><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:V_sGLiPBpWU\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?i=X23m6hA-koQ:SLe_ipQ43uA:V_sGLiPBpWU\" border=\"0\"></img></a><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:F7zBnMyn0Lo\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?i=X23m6hA-koQ:SLe_ipQ43uA:F7zBnMyn0Lo\" border=\"0\"></img></a><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:gIN9vFwOqvQ\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?i=X23m6hA-koQ:SLe_ipQ43uA:gIN9vFwOqvQ\" border=\"0\"></img></a><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:6et-BrRH4jw\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?d=6et-BrRH4jw\" border=\"0\"></img></a><a href=\"http://feeds.feedburner.com/~ff/Co-optimus?a=X23m6hA-koQ:SLe_ipQ43uA:qj6IDK7rITs\"><img src=\"http://feeds.feedburner.com/~ff/Co-optimus?d=qj6IDK7rITs\" border=\"0\"></img></a></div>";
        //tryParse(html);
        //db.DropTable(DBFeedItem.DB.TABLE_NAME);
        //db.close();
        //addStarters();
        if(getAutoPoll()) {
            RSSCastReceiver.SetupPolling(this, getAutoPollInMinutes());
        }

        FragmentManager fragmentManager = getSupportFragmentManager();

        FeedsFragment feedsFrag = getFeedsFragment();
        FragmentTransaction ft = fragmentManager.beginTransaction();
        ft.replace(R.id.container, feedsFrag, FeedsFragment.class.getName());
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
        feedsFrag.setFeedId(currentFeedId);
        inSettings=false; // fla


    }

    /**
     * Gets the user's preference to use auto polling
     * @return true or false to use auto polling
     */
    private boolean getAutoPoll(){
        SharedPreferences prefs=
                getSharedPreferences(
                        getString(
                                R.string.preferences_gambonereader),
                        Context.MODE_PRIVATE);
        return prefs.getBoolean(
                getString(R.string.preferences_enableAuto),
                false);

    }

    /**
     * Gets the user's preference in minutes how often to auto poll
     * @return value in minutes on how often to auto poll
     */
    private int getAutoPollInMinutes(){
        SharedPreferences prefs=
                getSharedPreferences(
                        getString(
                                R.string.preferences_gambonereader),
                        Context.MODE_PRIVATE);
        return prefs.getInt(
                getString(R.string.preference_autoPollInMinutes),
                60);

    }

    /**
     * Clears the FeedItem table of all it's feeds.
     * Used primarily for debugging and cleaning up messes.
     */
    private void clearTables(){
            DBFeedItem db = new DBFeedItem(this);
            db.clearTable();
            db.close();
    }

    /**
     * setups up any UI items.
     */
    private void setupUI(){
        //not really used.  Only initially for debugging
        //tvStatus = (TextView)findViewById(R.id.StatusText);

    }

    /**
     * Registers a broadcast receiver for this activity
     * we filter out all broadcasts that we don't care about
     * just the ones our application produces.
     */
    private void registerReceiver(){
        IntentFilter filter = new IntentFilter();
        filter.addAction(RSSGetService.NOTIFICATION);
        filter.addAction(RSSGetService.FEED_START);
        filter.addAction(RSSGetService.FEED_DONE);
        filter.addAction(RSSGetService.FEEDITEM_IMAGE_DONE);
        filter.addAction(RSSGetService.FEED_IMAGE_DONE);

        filter.addAction(getString(R.string.broadcast_removed_feed));
        filter.addAction(getString(R.string.broadcast_newfeed_added));

        registerReceiver(receiver, filter);
    }

    @Override
    protected void onResume() {
        //resetup the UI
        setupUI();
        //re-register the receiver.
        registerReceiver();

        super.onResume();
    }

    @Override
    protected void onResumeFragments(){
        if(mNavigationDrawerFragment != null){
            mNavigationDrawerFragment.loadUserFeeds();
        }
        super.onResumeFragments();
    }


    @Override
    protected void onPause() {
        //if our activity pauses it's proper to unregister the
        //broadcast receiver
        unregisterReceiver(receiver);
        super.onPause();
    }

    @Override
    protected void onSaveInstanceState(Bundle b){
        // in case we want to launch other activities from the
        // app we should remember what feed we are looking at.
        b.putInt("currentFeedId",currentFeedId);
        super.onSaveInstanceState(b);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        //looks like we're really not doing anything here currently
        // before the Settings portion was an activity.  Now it's a fragment
        // it's probably safe to pull this stuff.
        /*
        currentFeedId = savedInstanceState.getInt("currentFeedId");
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment frag = fragmentManager.findFragmentByTag(FeedsFragment.class.getName());
        if(frag != null){
            //currentFeedFrag = (FeedsFragment)frag;
        }
        */


    }

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        setupUI();

        //re-bind the background service
        Intent intent = new Intent(this, RSSGetService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
     protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mConnection != null && mServiceBound) {
            unbindService(mConnection);
            mServiceBound = false;
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Unbind from the service
        if (mConnection != null && mServiceBound) {
            unbindService(mConnection);
            mServiceBound = false;
        }
    }

    /**
     * ServiceConnection to our RSSGetService that does all the work.
     */
    private ServiceConnection mConnection = new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            RSSGetService.LocalBinder binder = (RSSGetService.LocalBinder)service;
            mService = binder.getService();
            mServiceBound = true;
            if(mAttemptedToRefreshWhileNotBound){
                Log.i("onFragRefresh","Attempting refresh after rebound.");
                onFragmentRequestRefresh(currentFeedId,true);
                mAttemptedToRefreshWhileNotBound=false; //reset
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mServiceBound = false;
        }
    };

    public Bitmap getFeedBitmap(int feedId){
        if(mNavigationDrawerFragment != null){
            return mNavigationDrawerFragment.getFeedBitmap(feedId);
        }else{
            return null;
        }
    }

    /**
     *
     * @param feed FeedItem object that was selected from navigation
     * @param position FeedItem's position in the list.
     */
    @Override
    public void onNavigationDrawerItemSelected(MyFeed feed, int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        if(mNavigationDrawerFragment != null) {
            if(mNavigationDrawerFragment.mDrawerListView != null) {

                if(feed == null){
                    return ; // quit in case it's null.
                }

                //update the title in the aciton bar
                mTitle = feed.getTitle();
                setTitle(feed.getTitle());

                currentFeedId = feed.getId(); // update the current feed item

                getFeedsFragment().setFeedId(currentFeedId);

                inSettings=false; // flag to use in case we need to know


            }
        }
    }


    /**
     *
     * @param feedId id of the feed that was attached to view
     */
    public void onSectionAttached(int feedId) {
        if(feedId >0) { // it's a specific feed
            DBMyFeed db = new DBMyFeed(this);
            MyFeed feed = db.getFeed(feedId);
            db.close();
            mTitle = feed.getTitle();

        }else if(feedId==-1){ // it's settings
            mTitle = "Settings";
        }else{ // it's all
            mTitle="All";
        }
        setTitle(mTitle); // set the title
    }

    /**
     * Handles the FeedsFragment requesting a refresh
     * @param feedId feed id to refresh
     * @param manual was requested by the user
     */
    public void onFragmentRequestRefresh(int feedId, boolean manual){
        // tell the service to process/update the feed.
        if(feedId >=0) {
            //this.mrLayout.setRefreshing(true);
           if(mServiceBound) {
                mService.process(feedId, manual);
           }else{
               //somehow the service got unbound.  Let's rebind it then attempt to query on rebind.
               currentFeedId = feedId;
               mAttemptedToRefreshWhileNotBound = true;
               Log.i("onFragRefresh","Service is being rebound.");
               Intent intent = new Intent(this, RSSGetService.class);
               bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
           }
        }else{
            //should not be refreshing anything else is settings or favorites
            Log.i("onFragRefresh", String.valueOf(feedId));
        }
    }



    public void restoreActionBar() {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        actionBar.setDisplayShowTitleEnabled(true);
        actionBar.setTitle(mTitle);

        actionBar.setElevation(0.0f);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!mNavigationDrawerFragment.isDrawerOpen()) {
            // Only show items in the action bar relevant to this screen
            // if the drawer is not showing. Otherwise, let the drawer
            // decide what to show in the action bar.
            getMenuInflater().inflate(R.menu.main, menu);
            restoreActionBar();

            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if(id == R.id.action_setasread){
            if(!inSettings) {
                getFeedsFragment().markAllAsRead(getApplicationContext());
            }
        }
        if (id == R.id.action_refresh) {
            //clearTables();
            if(currentFeedId>=0 && !inSettings) {
                onFragmentRequestRefresh(currentFeedId, true);
            }
            return true;
        }
        if (id == R.id.action_settings) {
            //clearTables();
            Intent settings = new Intent(this,SettingsActivity.class);
            startActivity(settings);
            return true;
        }

        /*
        if (id == R.id.action_statistics) {
            Intent intent = new Intent(this, Statistics.class);
            startActivity(intent);
            return true;
        }
        */
        return super.onOptionsItemSelected(item);
    }



    private FeedsFragment getFeedsFragment(){
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment frag = fragmentManager.findFragmentByTag(FeedsFragment.class.getName());
        FeedsFragment fFrag;
        if(frag == null){
            fFrag = FeedsFragment.newInstance();
        }else{
            fFrag = (FeedsFragment)frag;
        }
        return fFrag;
    }

    /**
     * handles broadcasts from RSSGetService and other parts of the app.
     */
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            StringBuilder msg = new StringBuilder();

            if(intent.getAction().equals(RSSGetService.FEED_START)){
                msg.append(intent.getIntExtra(getString(R.string.feed_id),0));
                msg.append("-");
                msg.append(intent.getStringExtra(getString(R.string.feedTitle)));
                msg.append(" has started...");
            }else if(intent.getAction().equals(RSSGetService.FEED_DONE)){
                int feedId = intent.getIntExtra(getString(R.string.feed_id),0);
                msg.append(feedId);
                msg.append("-");
                msg.append(intent.getStringExtra(getString(R.string.feedTitle)));
                msg.append(" has finished.");
                FeedsFragment fFrag = getFeedsFragment();
                if((fFrag != null) && (fFrag.getFeedId() == 0 || fFrag.getFeedId() == feedId)){
                    fFrag.loadFeed(getApplicationContext());
                    mNavigationDrawerFragment.updateFeedItem(feedId);
                    //getActionBar().setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_action_important_dark));
                }

            }else if(intent.getAction().equals(RSSGetService.FEEDITEM_IMAGE_DONE)){
                int feedId=intent.getIntExtra(getString(R.string.feed_id),0);
                int feedItemId=intent.getIntExtra(getString(R.string.feed_item_id), 0);
                FeedsFragment fFrag = getFeedsFragment();
                if((fFrag != null)) {
                    fFrag.setBitmap(feedItemId);
                }
            }else if(intent.getAction().equals(RSSGetService.FEED_IMAGE_DONE)){
                int feedId=intent.getIntExtra(getString(R.string.feed_id),0);
                if((mNavigationDrawerFragment != null)) {
                    mNavigationDrawerFragment.setFavicon(feedId);
                }
            } else if (intent.getAction().equals(context.getString(R.string.broadcast_newfeed_added))){
                if(mService != null){
                    int feedId=intent.getIntExtra(getString(R.string.feed_id),0);
                    mService.process(feedId,true);
                    if(mNavigationDrawerFragment != null){
                        mNavigationDrawerFragment.loadUserFeeds();
                    }
                }
            } else if (intent.getAction().equals(context.getString(R.string.broadcast_removed_feed))){
                    int feedId=intent.getIntExtra(getString(R.string.feed_id),0);

                    if(mNavigationDrawerFragment != null){
                        mNavigationDrawerFragment.loadUserFeeds();
                        if(currentFeedId == feedId){
                            // switch the user back to all
                            mNavigationDrawerFragment.selectItem(0);
                        }
                    }
            }

        }
    };

    public void feedRemoved(int feedId){
        if(mNavigationDrawerFragment != null){
            mNavigationDrawerFragment.loadUserFeeds();
            if(currentFeedId == feedId){
                // switch the user back to all
                currentFeedId=0; //All
            }
            mNavigationDrawerFragment.removeFeed(feedId,false);

        }

    }

    public void feedAdded(int feedId){
        if(mService != null){
            mService.process(feedId,true);
            if(mNavigationDrawerFragment != null){
                mNavigationDrawerFragment.loadUserFeeds();
            }
        }
    }


}
